package org.atlantis.ymer.server.transport;

import org.atlantis.ymer.DataForwarder;
import org.atlantis.ymer.DisconnectReason;
import org.atlantis.ymer.Transport;
import org.atlantis.ymer.WebSession;
import org.atlantis.ymer.WebSessionFactory;
import org.atlantis.ymer.command.Command;
import org.atlantis.ymer.command.JsonCommand;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class AbstractTransport implements Transport {

	private static final Logger log = LoggerFactory.getLogger(AbstractTransport.class);

	private WebSessionFactory sessionFactory;

	public AbstractTransport set(WebSessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
		return this;
	}

	protected abstract class AbstractDataForwarder implements DataForwarder {

		protected ChannelHandlerContext ctx;
		protected WebSession webSession;

		protected AbstractDataForwarder(ChannelHandlerContext ctx, final WebSession webSession, boolean persistConnection) {
			this.ctx = ctx;
			this.webSession = webSession;
			// 如果不是持续连接（如长轮询）则不需要监听TCP连接状态。
			if (!persistConnection) return;
			this.ctx.getChannel().getCloseFuture().addListener(new ChannelFutureListener() {
				@Override
				public void operationComplete(ChannelFuture future) throws Exception {
					webSession.close(DisconnectReason.CLOSE_DISCONNECT);
				}
			});
		}

		protected Channel getChannel() {
			Channel channel = ctx.getChannel();
			if (channel.isConnected()) return channel;
			channel.close();
			webSession.close(DisconnectReason.CLOSE_DISCONNECT);
			return null;
		}

		protected void resetCtx(ChannelHandlerContext ctx) {
			this.ctx = ctx;
		}
	}

	protected WebSession tryGetWebSession(String webSessionId) {
		WebSession webSession = sessionFactory.get(webSessionId);
		if (webSession != null && webSession.isConnected()) return webSession;
		log.warn("The WebSessioin is null or disconnect with id: {}.", webSessionId);
		return null;
	}

	protected WebSession createNewWebSession() {
		return sessionFactory.create();
	}

	protected void passContentToWebSession(String content, WebSession webSession) {
		Command command = null;
		try {
			command = JsonCommand.parseJson(content);
		} catch (Throwable e) {
			webSession.close(DisconnectReason.createException(e));
			return;
		}
		if (command != null) webSession.onData(command);
	}
}
